package com.nk.system.utils;

import java.io.File;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.BufferedReader;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.io.StringReader;

import org.apache.log4j.Logger;

public class UTextFile {

    private Logger log = Logger.getLogger(UTextFile.class);
    private static final long MemSize = (long) 256 * (long) 1024;//(long) 4194304;
    private boolean streamMode = false;
    private File oriFile = null;
    private String oriEncode = null;
    private StringBuffer buff = null;
    private InputStream is = null;
    private InputStreamReader isr = null;
    private BufferedReader br = null;
    private int lineIndex = 0;

    private void processConstructor(InputStream is, String encode, boolean streamMode) throws UnsupportedEncodingException {
        this.streamMode = streamMode;
        if (is != null) {
            try {
                this.oriEncode = encode;
                if (Charset.isSupported(this.oriEncode)) {
                    this.is = is;
                    this.isr = new InputStreamReader(is, this.oriEncode);
                    if (this.streamMode == false) {
                        BufferedReader buffered = new BufferedReader(this.isr);
                        this.buff = new StringBuffer();
                        String buffLine = "";
                        while ((buffLine = buffered.readLine()) != null) {
                            buff.append(buffLine.concat("\n"));
                        }
                    }
                } else {
                    throw new UnsupportedEncodingException("Charset encoding [" + this.oriEncode + "] is not supported");
                }
            } catch (Exception ex) {
                log.error("processConstructor", ex);
            }
        } else {
            System.err.println("UTextFile : UTextFile - InputStream is null");
        }
    }

    public UTextFile(File textFile, String encode) throws UnsupportedEncodingException {
        if (textFile != null) {
            try {
                this.oriFile = textFile;
                this.oriEncode = encode;
                InputStream input = new FileInputStream(textFile);
                if (textFile.length() > UTextFile.MemSize) {
                    this.processConstructor(input, encode, true);
                } else {
                    this.processConstructor(input, encode, false);
                }
            } catch (Exception ex) {
                log.error("UTextFile", ex);
            }
        } else {
            System.err.println("UTextFile : UTextFile - Text File is null");
        }
    }

    public UTextFile(File textFile) throws UnsupportedEncodingException {
        this(textFile, "UTF-8");
    }

    public UTextFile(InputStream is, String encode) throws UnsupportedEncodingException {
        if (is != null) {
            this.processConstructor(is, encode, true);
        } else {
            System.err.println("UTextFile : UTextFile - InputStream is null");
        }
    }

    public UTextFile(InputStream is) throws UnsupportedEncodingException {
        if (is != null) {
            this.processConstructor(is, "UTF-8", true);
        } else {
            System.err.println("UTextFile : UTextFile - InputStream is null");
        }
    }

    public boolean writeFile(File textFile, String encode) throws UnsupportedEncodingException {
        if (textFile != null) {
            try {
                if (Charset.isSupported(encode)) {
                    FileOutputStream fos = new FileOutputStream(textFile);
                    OutputStreamWriter osw = new OutputStreamWriter(fos, encode);
                    if (this.streamMode) {
                        BufferedReader buffered = new BufferedReader(this.isr);
                        this.buff = new StringBuffer();
                        String buffLine = "";
                        while ((buffLine = buffered.readLine()) != null) {
                            osw.write(buffLine + "\n");
                        }
                    } else {
                        osw.write(this.buff.toString());
                    }
                    return true;
                } else {
                    throw new UnsupportedEncodingException("Charset encoding [" + encode + "] is not supported");
                }
            } catch (Exception ex) {
                log.error("writeFile", ex);
                return false;
            }
        } else {
            System.err.println("UTextFile : writeFile - Unable to write to null file");
            return false;
        }
    }

    public boolean writeFile(File textFile) throws UnsupportedEncodingException {
        return this.writeFile(textFile, this.oriEncode);
    }

    public boolean saveFile(String encode) throws UnsupportedEncodingException {
        return this.writeFile(this.oriFile, encode);
    }

    public boolean saveFile() throws UnsupportedEncodingException {
        return this.writeFile(this.oriFile, this.oriEncode);
    }

    public String getTextString() {
        if (this.streamMode) {
            BufferedReader buffered = new BufferedReader(this.isr);
            this.buff = new StringBuffer();
            String buffLine = "";
            try {
                while ((buffLine = buffered.readLine()) != null
                        && (this.buff.toString().getBytes().length <= UTextFile.MemSize)) {
                    this.buff.append(buffLine.concat("\n"));
                }
                return this.buff.toString();
            } catch (Exception ex) {
                log.error("getTextString", ex);
                return null;
            } finally {
                try {
                    isr = new InputStreamReader(this.is, this.oriEncode);
                } catch (Exception ex) {
                    log.error("getTextString", ex);
                }
            }
        } else {
            return this.buff.toString();
        }
    }

    public boolean resetStream() {
        if (this.streamMode && this.br != null) {
            try {
                this.br.reset();
                return true;
            } catch (Exception ex) {
                log.error("resetStream", ex);
                return false;
            }
        } else {
            return false;
        }
    }

    public String readln() {
        if (this.streamMode) {
            if (this.br == null) {
                this.br = new BufferedReader(this.isr);
                this.lineIndex = 0;
            }
        } else {
            if (this.br == null) {
                this.br = new BufferedReader(new StringReader(this.buff.toString()));
                this.lineIndex = 0;
            }
        }
        String buffLine = "";
        try {
            if ((buffLine = this.br.readLine()) != null) {
                this.lineIndex++;
                return buffLine;
            } else {
                this.br = null;
                this.lineIndex = 0;
                return null;
            }
        } catch (Exception ex) {
            log.error("readln", ex);
            return null;
        }
    }
}
